/*
 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2019年12月11日
 * <修改描述:>
 */
package com.tx.component.social.support.github;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import com.tx.component.security.exception.SocialAuthorizeException;
import com.tx.component.social.SocialLoginPlugin;
import com.tx.component.social.context.SocialLoginContext;
import com.tx.component.social.model.SocialAccountType;
import com.tx.component.social.model.SocialAccountTypeEnum;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.util.MessageUtils;

import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthConfig.AuthConfigBuilder;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthDefaultRequest;
import me.zhyd.oauth.request.AuthGithubRequest;
import me.zhyd.oauth.request.AuthRequest;

/**
 * GITHUB登陆插件<br/>
 * 
 * @author  Administrator
 * @version  [版本号, 2019年12月11日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
//https://docs.github.com/cn/developers/apps/building-oauth-apps/authorizing-oauth-apps
//access_token10分钟有效期
public class GHLoginPlugin extends SocialLoginPlugin<GHLoginPluginConfig> {
    
    ///** 日志记录器 */
    //private Logger logger = LoggerFactory.getLogger(GHLoginPlugin.class);
    //
    ///** code请求URL */
    //private static final String CODE_REQUEST_URL = "https://github.com/login/oauth/authorize";
    //
    ///** uid请求URL */
    //private static final String UID_REQUEST_URL = "https://github.com/login/oauth/access_token";
    //
    ///** userInfo请求URL */
    //private static final String USER_INFO_REQUEST_URL = "https://api.github.com/user";
    
    //private OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
    
    /** "REDIRECT_URL"属性名称 */
    private static final String REDIRECT_URL_ATTRIBUTE_NAME = GHLoginPlugin.class
            .getName() + ".REDIRECT_URL";
    
    /**
     * @return
     */
    @Override
    public String getName() {
        return "Github登陆插件";
    }
    
    /**
     * @return
     */
    @Override
    public String getVersion() {
        return "1.0";
    }
    
    /**
     * @return
     */
    @Override
    public SocialAccountType getSocialAccountType() {
        return SocialAccountTypeEnum.GH;
    }
    
    /**
     * @return
     */
    @Override
    public String getPrefix() {
        return "plugin.login.gh";
    }
    
    /**
     * 获取code的handle<br/>
     * @param viewName
     * @param redirectUri
     * @param scope
     * @param request
     * @return
     */
    @Override
    public String authorize(String redirectUri, String state,
            List<String> scopes, HttpServletRequest request) {
        AssertUtils.notEmpty(redirectUri, "redirectUri is empty.");
        
        //写入state值
        HttpSession session = request.getSession();
        SocialLoginContext.getContext().saveState(session, state);
        session.setAttribute(REDIRECT_URL_ATTRIBUTE_NAME, redirectUri);
        
        GHLoginPluginConfig config = getConfig();
        AuthConfigBuilder acbuilder = AuthConfig.builder()
                .clientId(config.getClientId())
                .clientSecret(config.getClientSecret())
                .redirectUri(redirectUri);
        if (!CollectionUtils.isEmpty(scopes)) {
            acbuilder.scopes(scopes);
        }
        AuthRequest authRequest = new AuthGithubRequest(acbuilder.build());
        String authorize = authRequest.authorize(state);
        return authorize;
    }
    
    /**
     * @param code
     * @param state
     * @param request
     * @return
     * @throws SocialAuthorizeException
     */
    @Override
    public AuthUser login(String code, String state, HttpServletRequest request)
            throws SocialAuthorizeException {
        HttpSession session = request.getSession();
        String sessionState = SocialLoginContext.getContext().getState(session);
        if (!StringUtils.equals(state, sessionState)) {
            throw new SocialAuthorizeException(MessageUtils.format(
                    "state value is invalid.request_state:{}  session_state:{}",
                    state,
                    sessionState));
        }
        
        GHLoginPluginConfig config = getConfig();
        AuthConfigBuilder acbuilder = AuthConfig.builder()
                .clientId(config.getClientId())
                .clientSecret(config.getClientSecret());
        AuthDefaultRequest authRequest = new AuthGithubRequest(
                acbuilder.ignoreCheckState(true).build());
        
        @SuppressWarnings("unchecked")
        AuthResponse<AuthUser> resp = authRequest
                .login(AuthCallback.builder().code(code).build());
        if (!resp.ok()) {
            throw new SocialAuthorizeException("获取第三方登陆用户信息失败.");
        }
        
        AuthUser au = resp.getData();
        return au;
    }
    
    ///**
    // * 获取AccessToken<br/>
    // *    https://open.weibo.com/wiki/Oauth/access_token
    // * @param code
    // * @param state
    // * @param request
    // * @return
    // * @throws SocialAuthorizeException
    // */
    //@Override
    //public SocialAccessToken getAccessToken(String code, String state,
    //        HttpServletRequest request) throws SocialAuthorizeException {
    //    HttpSession session = request.getSession();
    //    String sessionState = SocialLoginContext.getContext().getState(session);
    //    if (!StringUtils.equals(state, sessionState)) {
    //        throw new SocialAuthorizeException(MessageUtils.format(
    //                "state value is invalid.request_state:{}  session_state:{}",
    //                state,
    //                sessionState));
    //    }
    //    
    //    //从会话中获取redirectUri
    //    String redirectUri = (String) session
    //            .getAttribute(REDIRECT_URL_ATTRIBUTE_NAME);
    //    GHLoginPluginConfig config = getConfig();
    //    Map<String, String> parameterMap = new HashMap<>();
    //    parameterMap.put("grant_type", "authorization_code");
    //    String appKey = config.getClientId();
    //    String appSecret = config.getClientSecret();
    //    parameterMap.put("client_id", appKey);
    //    parameterMap.put("client_secret", appSecret);
    //    parameterMap.put("code", code);
    //    parameterMap.put("redirect_uri", redirectUri);
    //    String result = HttpClientUtils.post(UID_REQUEST_URL, parameterMap);
    //    
    //    logger.info(
    //            "--- getAccessToken:{client_id:{},client_secret:{},code:{},result:{}}",
    //            appKey,
    //            appSecret,
    //            code,
    //            result);
    //    //getAccessToken:{client_id:e89c345917ce6375e634,client_secret:c9757c70a8af2c01e2a85b5f6e06fc240c122867,code:48896d56a152d946da65,result:access_token=dc400027043a1980222dcdf3fb90858b1b7ac75b&scope=&token_type=bearer}
    //    //access_token=dc400027043a1980222dcdf3fb90858b1b7ac75b&scope=&token_type=bearer
    //    //Map<String, String> tokenMap = WebUtils.parse(result);
    //    JsonNode tokenJNode = JsonUtils.toTree(result);
    //    String accessToken = tokenJNode.get("access_token").asText();
    //    
    //    SocialAccessToken token = new SocialAccessToken(
    //            SocialAccountTypeEnum.GH);
    //    token.setAccessToken(accessToken);
    //    token.setExpiresIn(DateTime.now().plusMinutes(10).toDate().getTime());
    //    if (StringUtils.isEmpty(token.getAccessToken())) {
    //        throw new SocialAuthorizeException("获取AccessToken失败.");
    //    }
    //    return token;
    //}
    //
    ///**
    // * 获取用户信息<br/>
    // * @param accessToken
    // * @param request
    // * @return
    // */
    //@Override
    //public SocialUserInfo getUserInfo(SocialAccessToken accessToken,
    //        HttpServletRequest request) {
    //    AssertUtils.notNull(accessToken, "accessToken is null.");
    //    AssertUtils.notEmpty(accessToken.getAccessToken(),
    //            "accessToken.accessToken is empty.");
    //    
    //    Map<String, String> params = new HashMap<String, String>();
    //    params.put("access_token", accessToken.getAccessToken());
    //    
    //    Request req = new Request.Builder().url(USER_INFO_REQUEST_URL)
    //            //.method("get", null)
    //            .header(HttpHeaders.AUTHORIZATION,
    //                    "token " + accessToken.getAccessToken())
    //            .build();
    //    
    //    String result = "";
    //    try {
    //        Response response = this.okHttpClient.newCall(req).execute();
    //        result = response.body().string();
    //    } catch (IOException e) {
    //        throw new HttpExcutingException(true, "Http请求IO流异常.", e);
    //    }
    //    //{"login":"240638006","id":2492318,"node_id":"MDQ6VXNlcjI0OTIzMTg=","avatar_url":"https://avatars.githubusercontent.com/u/2492318?v=4","gravatar_id":"","url":"https://api.github.com/users/240638006","html_url":"https://github.com/240638006","followers_url":"https://api.github.com/users/240638006/followers","following_url":"https://api.github.com/users/240638006/following{/other_user}","gists_url":"https://api.github.com/users/240638006/gists{/gist_id}","starred_url":"https://api.github.com/users/240638006/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/240638006/subscriptions","organizations_url":"https://api.github.com/users/240638006/orgs","repos_url":"https://api.github.com/users/240638006/repos","events_url":"https://api.github.com/users/240638006/events{/privacy}","received_events_url":"https://api.github.com/users/240638006/received_events","type":"User","site_admin":false,"name":"Tim.PQY","company":"ChongQingTianXinWangLuoKeJiYouXianGongSi","blog":"","location":null,"email":"240638006@qq.com","hireable":true,"bio":null,"twitter_username":null,"public_repos":14,"public_gists":0,"followers":1,"following":2,"created_at":"2012-10-05T07:58:47Z","updated_at":"2022-04-07T09:31:10Z"}
    //    //HttpClientUtils.get(USER_INFO_REQUEST_URL, params);
    //    logger.info(
    //            "--- GHLoginPlugin.getUserInfo:{access_token:{},openid:{},result:{}}",
    //            accessToken.getAccessToken(),
    //            accessToken.getUniqueId(),
    //            result);
    //    //从接口中提取数据
    //    //getUserInfo:{access_token:b7ae403f31c13fb524c9777b7aed8aa3824eb475,openid:null,result:{"login":"240638006","id":2492318,"node_id":"MDQ6VXNlcjI0OTIzMTg=","avatar_url":"https://avatars3.githubusercontent.com/u/2492318?v=4","gravatar_id":"","url":"https://api.github.com/users/240638006","html_url":"https://github.com/240638006","followers_url":"https://api.github.com/users/240638006/followers","following_url":"https://api.github.com/users/240638006/following{/other_user}","gists_url":"https://api.github.com/users/240638006/gists{/gist_id}","starred_url":"https://api.github.com/users/240638006/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/240638006/subscriptions","organizations_url":"https://api.github.com/users/240638006/orgs","repos_url":"https://api.github.com/users/240638006/repos","events_url":"https://api.github.com/users/240638006/events{/privacy}","received_events_url":"https://api.github.com/users/240638006/received_events","type":"User","site_admin":false,"name":"Tim.PQY","company":"ChongQingTianXinWangLuoKeJiYouXianGongSi","blog":"","location":null,"email":"240638006@qq.com","hireable":true,"bio":null,"public_repos":14,"public_gists":0,"followers":1,"following":2,"created_at":"2012-10-05T07:58:47Z","updated_at":"2020-01-02T03:53:42Z"}}
    //    //{"login":"240638006","id":2492318,"node_id":"MDQ6VXNlcjI0OTIzMTg=","avatar_url":"https://avatars3.githubusercontent.com/u/2492318?v=4","gravatar_id":"","type":"User","site_admin":false,"name":"Tim.PQY","company":"ChongQingTianXinWangLuoKeJiYouXianGongSi","blog":"","location":null,"email":"240638006@qq.com","hireable":true,"bio":null,"public_repos":14,"public_gists":0,"followers":1,"following":2,"created_at":"2012-10-05T07:58:47Z","updated_at":"2020-01-02T03:53:42Z"}
    //    //Map<String, String> userMap = WebUtils.parse(result);
    //    JsonNode node = JsonUtils.toTree(result);
    //    String uniqueId = node.get("id").asText();
    //    String username = node.get("login").asText();
    //    String headImgUrl = node.get("avatar_url") != null
    //            ? node.get("avatar_url").asText()
    //            : null;
    //    String name = node.get("name").asText();
    //    String location = node.get("location") != null
    //            ? node.get("location").asText()
    //            : null;
    //    String company = node.get("company") != null
    //            ? node.get("company").asText()
    //            : null;
    //    String blog = node.get("blog") != null ? node.get("blog").asText()
    //            : null;
    //    String email = node.get("email") != null ? node.get("email").asText()
    //            : null;
    //    
    //    //SocialUserInfo
    //    SocialUserInfo user = new SocialUserInfo();
    //    user.setId(uniqueId);
    //    user.setSocialUsername(username);
    //    user.setHeadImgUrl(headImgUrl);
    //    user.setSex(null);
    //    user.setUniqueId(uniqueId);
    //    
    //    JSONObject json = user.getAttributeJSONObject();
    //    json.put("name", name);
    //    json.put("location", location);
    //    json.put("company", company);
    //    json.put("blog", blog);
    //    json.put("email", email);
    //    return user;
    //}
    //
    ///**
    // * 获取登陆用户的第三方唯一键<br/>
    // * @param accessToken
    // * @param request
    // * @return
    // * @throws SocialAuthorizeException
    // */
    //@Override
    //public String getUniqueId(SocialAccessToken accessToken,
    //        HttpServletRequest request) throws SocialAuthorizeException {
    //    AssertUtils.notNull(accessToken, "accessToken is null.");
    //    AssertUtils.notEmpty(accessToken.getAccessToken(),
    //            "accessToken.accessToken is empty.");
    //    
    //    SocialUserInfo userInfo = getUserInfo(accessToken, request);
    //    String uniqueId = userInfo.getUniqueId();
    //    return uniqueId;
    //}
}
